import random

import pyrtl
from pyrtl import *
import io
# declare blocs and registers
memory = MemBlock(bitwidth=64, addrwidth=8, name='memory')

write_address = Input(bitwidth=8, name='write_address')
write_data = Input(bitwidth=64, name='write_data')
write_enable = Input(bitwidth=1, name='write_enable')

read_address = Input(bitwidth=8, name='read_address')
read_data = Output(bitwidth=64, name='read_data')

# connect them
read_data <<= memory[read_address]

WE = MemBlock.EnabledWrite
memory[write_address] <<= WE(write_data, write_enable)


simvals = {
    'write_enable':       "00111111110000000000000000",
    'write_address':      "00112345670000000000000000",
    'write_data':         "00123456789990000000000000",
    'read_address':       "00000000000000000123456777"
}

memory_init = {addr: 9 for addr in range(8)}
memvals = {memory: memory_init}

sim_trace = pyrtl.SimulationTrace()
sim = pyrtl.Simulation(tracer=sim_trace, memory_value_map=memvals)
for cycle in range(len(simvals['write_enable'])):
    sim.step({k: int(v[cycle]) for k, v in simvals.items()})
sim_trace.render_trace()


print("--- Verilog for the Counter ---")
with io.StringIO() as vfile:
    pyrtl.OutputToVerilog(vfile)
    print(vfile.getvalue())


print("--- Verilog for the TestBench ---")
with io.StringIO() as tbfile:
    pyrtl.output_verilog_testbench(dest_file=tbfile, simulation_trace=sim_trace)
    print(tbfile.getvalue())